function varargout = gui_main(varargin)
% GUI_MAIN MATLAB code for gui_main.fig
%      GUI_MAIN, by itself, creates a new GUI_MAIN or raises the existing
%      singleton*.
%
%      H = GUI_MAIN returns the handle to a new GUI_MAIN or the handle to
%      the existing singleton*.
%
%      GUI_MAIN('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in GUI_MAIN.M with the given input arguments.
%
%      GUI_MAIN('Property','Value',...) creates a new GUI_MAIN or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before gui_main_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to gui_main_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help gui_main

% Last Modified by GUIDE v2.5 28-Jan-2013 13:19:11

% TODO: Specify default player;

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @gui_main_OpeningFcn, ...
                   'gui_OutputFcn',  @gui_main_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Display name of working file in title bar and in-figure label
function gui_show_filename(handles, inFile)
try
    if(strncmp(inFile.kind, 'video',5))
        namelabel = sprintf('%s.%s',...
            inFile.namePrefixNoPath, ...
            inFile.fileExt);
    else
        namelabel = sprintf('(%s%0*d.%s,...)',...
            inFile.namePrefixNoPath, ...
            inFile.indFieldLength, ...
            inFile.frameRangeArr(1), ...
            inFile.fileExt);
    end

    set(handles.main_figure, 'Name', ...
        [namelabel ' - AEO-Light v' handles.versionStr]);
    set(handles.film_name_label, 'String', namelabel);
catch exception
    gui_exception(exception);
end


% --- Executes just before gui_main is made visible.
function gui_main_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to gui_main (see VARARGIN)

global globalDoVisualize globalShotFileNamePrefix globalShotFileExt
globalDoVisualize = false;
globalShotFileNamePrefix = '';
globalShotFileExt = '';

% Check if the application is run on a registered computer.
if (~isRegistered())
	msgbox({'Thank you for your interest in AEO-Light.', ...
		'', ...
		'It appears that you are running a copy of AEO-Light that', ...
		'is not intended for the computer on which you are using it.', ...
		'', ...
		'To obtain a suitable copy, please, register your computer' ...
		'or contact Borislav Karaivanov at ', ...
		'', ...
		'                    karaivan@math.sc.edu', ...
		'', ...
		}, ...
		'Unauthorized user', 'error');
	close(hObject);
	return;
end

try
    
    % Set the version number. (This is used everywhere, including
    % the name of the executable and the GUI windows title, and in the
    % user-license-agreement check.)
    versionStr = '0.8';
    handles.versionStr = versionStr;

    % Choose default command line output for gui_main
    handles.output = hObject;

    % Set the default project parameters
    dflt.source = '';
    dflt.output_directory = '';
    dflt.scratch_directory = '';
    dflt.scratch_directory2 = '';
    dflt.frame_in = 1;
    dflt.frame_out = Inf;
    dflt.frame_min = 1;
    dflt.frame_max = Inf;
    dflt.sound_bounds_arr = [ 0,0,0 ];
    dflt.do_visualization = false;
    dflt.do_log_file = false;
    dflt.do_prep_for_video = true;
    dflt.frames_per_batch_rough = 200;
    dflt.read_write_attempts_rough = 5;
    dflt.signals_per_mask = 100;
    dflt.do_poly_fit = false;
    dflt.moving_average_smoothing_passes = 1;
    dflt.moving_average_span = 15;
    dflt.poly_fit_degree = [true,true,true,true];
    dflt.frames_for_overlap_guess = 400;
    dflt.initial_search_radius = 10;
    dflt.local_min_neighborhood_radius = 5;
    dflt.max_rows_to_ignore = 150;
    dflt.max_rows_to_ignore_is_percent = false;
    dflt.overlap_threshold = 5;
    dflt.do_smooth_sound = false;
    dflt.smooth_sound_moving_average_span = 5;

    handles.default_project = dflt;
    handles.project = dflt;
    handles.unsaved_changes = false;

    guidata(hObject, handles);

    % Set the GUI name to appear in the window title.
    set(hObject, 'Name', ['AEO-Light v' versionStr]);

    img = usclogo();
    set(handles.logo,'CData',img);
    set(handles.logo,'Units','Pixels');
    figpos = getpixelposition(hObject);
    figwidth = figpos(3);

    pos = get(handles.logo,'Position');
    pos(3) = size(img,2) + 8;
    pos(4) = size(img,1) + 8;

    %re-center the logo in the figure window.
    pos(1) = (figwidth - pos(3))/2;

    set(handles.logo, 'Position', pos);

    % position the "clear" button
    set(handles.clear_button, 'Units', 'Pixels');
    set(handles.soundtrack_bounds_table, 'Units', 'Pixels');
    figpos = getpixelposition(handles.soundtrack_bounds_table);
    figwidth = figpos(3);
    figcenter = figpos(1) + (figwidth/2);

    pos = get(handles.clear_button, 'Position');
    pos(1) = figcenter - (pos(3)/2);
    pos(2) = figpos(2) - pos(4) - 4;
    set(handles.clear_button, 'Position', pos);

    % Set the name of the file where the copyright acceptance and user
    % preferences are to be stored.
    if(isunix)
        handles.userfile = '~/.aeo_light';
    else
        handles.userfile = [getenv('UserProfile') filesep 'aeo_light.cfg'];
    end

    % Update handles structure.
    guidata(hObject, handles);
catch exception
    gui_exception(exception);
end

ask = 1;

try
    
    filedat = load(handles.userfile, '-mat');
    if(isfield(filedat.pref, 'user_agreement') && ...
            strcmp(filedat.pref.user_agreement,versionStr))
        ask = 0;
    end
    handles.pref = filedat.pref;
    guidata(hObject, handles);
    
catch exception
    
    % Check if the copyright has been already accepted (i.e., if a copyright
    % acceptance file exists and has the appropriate copyright acceptance for
    % the current version).
    userAgreementText = ['Accept Copyright ' versionStr];

    tokExpr = '(?<tok>\w+)\s+(?<val>.*\S)';
    fid = fopen(handles.userfile, 'r');
    if (fid == -1)
        ask = 1;
    else
        uline = fgetl(fid);
        ask = 1;
        while ischar(uline)
            if (strfind(uline, userAgreementText))
                ask = 0;
                handles.pref.user_agreement = versionStr;
            else
               m = regexp(uline, tokExpr, 'names');
               if(~isempty(m))
                   switch lower(m.tok)
                       case 'scratch'
                           handles.pref.scratch_directory = m.val;
                           guidata(hObject, handles);
                   end
               end
            end
            uline = fgetl(fid);
        end
        fclose(fid);
    end
    
end

try
    % verify that all expected preference settings are loaded
    if(~isfield(handles, 'pref') || ~isfield(handles.pref, 'scratch_directory'))
        handles.pref.scratch_directory = '';
    end
    if(~isfield(handles.pref, 'scratch_directory2'))
        handles.pref.scratch_directory2 = '';
    end
    if(~isfield(handles.pref, 'do_prep_for_video_from_frames'))
        handles.pref.do_prep_for_video_from_frames = true;
    end
    if(~isfield(handles.pref, 'do_prep_for_video_from_video'))
        handles.pref.do_prep_for_video_from_video = false;
    end

    film(4).name = 'Phonofilm';
    film(4).offset = -14;
    film(3).name = 'Movietone Negative';
    film(3).offset = 11;
    film(2).name = 'Theatrical Standard';
    film(2).offset = 21;
    film(1).name = '16mm';
    film(1).offset = 25;

    if(~isfield(handles.pref, 'film_type'))
        handles.pref.film_type = film;
    else
        % squeeze in each of the defaults above if they're not present
        for i=1:4
            if(~isfield(handles.pref.film_type(i),'offset') || ...
                    isempty(handles.pref.film_type(i).offset))
                handles.pref.film_type(i) = film(3);
            end
            if(handles.pref.film_type(i).offset ~= film(i).offset)
                for j=size(handles.pref.film_type,2):i+1
                    handles.pref.film_type(j+1) = handles.pref.film_type(j);
                end
                handles.pref.film_type(i) = film(i);
            end
        end
    end

    if(~isfield(handles.pref, 'film_type_default'))
        handles.pref.film_type_default = 1;
    end

    guidata(hObject,handles);

    % If there is no evidence that the disclaimer has been accepted, then 
    % ask for acceptance now.
    if(ask)
        button = questdlg({...
            'Copyright (c) 2012, South Carolina Research Foundation',...
            'All Rights Reserved',...
            ['AEO-Light, Ver. ' versionStr ' (Beta)'],...
            '',...
            'This is beta software. See the Readme file for full disclaimer. ',...
            'Press [Agree] if you agree to the terms in the Readme file.'},...
            'AEO-Light', 'Exit', 'Agree', 'Exit');

        if(strcmp(button,'Agree'))
            handles.pref.user_agreement = versionStr;
            pref = handles.pref;
            save(handles.userfile, 'pref');
            guidata(hObject,handles);

            %fid = fopen(handles.userfile, 'a');
            %if(fid ~= -1)
            %    fprintf(fid,'%s\n',userAgreementText);
            %    fclose(fid);
            %end
        else
            close(hObject);
            return;
        end
    end

    % if default scratch directories haven't been set, ask for them now.
    try
        while(isempty(handles.pref.scratch_directory) || ...
                isempty(handles.pref.scratch_directory2))
            
            if gui_preferences('gui_main', handles.main_figure)
                handles = guidata(hObject);
                pref = handles.pref;
                save(handles.userfile, 'pref');
            end
        end
    catch exception
        gui_exception(exception);
    end

    % Open/create a project
    while true
        button = questdlg('', 'AEO-Light Project', 'New Project', ...
            'Open Project...', 'New Project');
        if(strcmp(button,'New Project'))
            new_project(hObject);
        elseif(strcmp(button,'Open Project...'))
            open_project(hObject);
        else
            close(hObject);
            return
        end

        handles = guidata(hObject);
        if(~ isfield(handles, 'projectStruct'))
            continue;
        end
        if(isempty(handles.projectStruct))
            continue;
        end

        break;
    end
catch exception
    gui_exception(exception);
end

%waitfor(f);

% UIWAIT makes soundtrack wait for user response (see UIRESUME)
%uiwait(handles.soundtrack);

function ret = close_project(handles)

try
    ret = true;
    if(isfield(handles,'unsaved_changes') && handles.unsaved_changes)
        while(true)
            button = questdlg('You have unsaved changes.',...
                'Abandon changes?',...
                'Cancel','Quit without Saving', 'Save and Quit', ...
                'Save and Quit');
            switch(button)
                case 'Cancel'
                    ret = false;
                    return;
                case 'Quit without Saving'
                    ret = true;
                    return;
                case 'Save and Quit'
                    project = handles.project;
                    project.projectStruct = handles.projectStruct;
                    if(isfield(handles,'project_file') && isempty(handles.project_file) == 0)
                        save_project(project, handles.project_file);
                        %handles.unsaved_changes = false;
                        %guidata(hObject, handles);
                        ret = true;
                        return;
                    else
                        [filename, pathname] = save_project_as(project);
                        if(filename == 0)
                            ret = false;
                            % don't return: loop again
                        else
                            %handles.project_file = [pathname filename];
                            %handles.unsaved_changes = false;
                            %guidata(hObject, handles);
                            ret = true;
                            return;
                        end
                    end
            end
        end
    end
catch exception
    gui_exception(exception);
end


function new_project(hObject)
try
    handles = guidata(hObject);
    handles.project = handles.default_project;
    new_film_source(hObject);
    handles = guidata(hObject);

    handles.project_file = [];
    handles.unsaved_changes = true;

    guidata(hObject, handles);
catch exception
    gui_exception(exception);
end

function new_film_source(hObject)
try
    handles = guidata(hObject);

    %frames_or_video = questdlg({...
    %    'Source Format',...
    %    '',...
    %    'If your film source is a set of DPX frame scans, select the',...
    %    'image folder. For video source, choose the video file.'},...
    %    'Choose Source Format', 'DPX Folder', 'Video File', 'DPX Folder');
    %if(strcmp(frames_or_video,'DPX Folder'))
    %    dirname = uigetdir('.','Open DPX Folder');

    [filename, pathname] = uigetfile( ...
        {'*.*',  'All Files (*.*)'; ...
            '*.dpx;*.DPX','DPX (all DPX frames in the folder will be used)';...
            '*.tif;*.TIF','Tiff (all tiff frames in the folder will be used)';...
            '*.avi',  'AVI files';...
            '*.mov',  'Quicktime files'}, ...
            'Choose film source');

    if isequal(filename, 0)
        return
    end

    % Append a file separator (i.e., \ for Windows or / for *nix)
    % to the directory name if it does not have one.
    %if (strcmpi(dirname(end), filesep) == false)
    %    dirname = [dirname filesep];
    %end

    if(isempty(handles.project.output_directory))
        if(isempty(handles.project.scratch_directory))
            projectStruct = gui_load_file(hObject, [pathname filename], ...
                0, Inf, handles.pref.scratch_directory);
        else
            projectStruct = gui_load_file(hObject, [pathname filename], ...
                0, Inf, handles.project.scratch_directory);
        end
    else
        projectStruct = gui_load_file(hObject, [pathname filename], 0, Inf, ...
            handles.project.output_directory);
    end
    if(isempty(projectStruct))
        return
    end

    handles.project.source = [pathname filename];

    handles.projectStruct = projectStruct;

    gui_show_filename(handles, projectStruct.inFile);

    set(handles.thumbnail_slider,'Min',projectStruct.inFile.frameRangeArr(1));
    set(handles.thumbnail_slider,'Max',projectStruct.inFile.frameRangeArr(2));
    set(handles.thumbnail_slider, 'Value', ...
        projectStruct.inFile.frameRangeArr(1));
    thumbnail_slider_Callback(handles.thumbnail_slider, '', handles);

    handles.project.frame_in = handles.projectStruct.inFile.frameRangeArr(1);
    handles.project.frame_out = handles.projectStruct.inFile.frameRangeArr(2);

    set(handles.frame_in_text, 'String', num2str(handles.project.frame_in));
    set(handles.frame_out_text, 'String', num2str(handles.project.frame_out));

    initTable = [ 0,0,0 ];
    set(handles.soundtrack_bounds_table, 'Data', initTable);

    handles.project.sound_bounds_arr = initTable;
    handles.unsaved_changes = true;

    guidata(hObject,handles);
catch exception
    gui_exception(exception);
end

function open_project(hObject)
try
    handles = guidata(hObject);

    [filename pathname] = uigetfile({'*.aeo;*.AEO','AEO-Light Project Files'},...
        'Open Project');
    if isequal(filename, 0)
        return
    end

    filedat = load([pathname filename],'-mat');

    handles.projectStruct = filedat.project.projectStruct;
    handles.project = rmfield(filedat.project, 'projectStruct');
    handles.project_file = [pathname filename];

    % read the source file to verify everything's still good.
    %projectStruct = gui_load_file(hObject, handles.project.source, 0, Inf, ...
    %    handles.project.output_directory);
    %if(isempty(projectStruct))
    %    return
    %end
    %
    %handles.projectStruct = projectStruct;
    projectStruct = handles.projectStruct;

    gui_show_filename(handles, projectStruct.inFile);

    % set the view slider to the full range
    set(handles.thumbnail_slider, 'Min', projectStruct.inFile.frameRangeArr(1));
    set(handles.thumbnail_slider, 'Max', projectStruct.inFile.frameRangeArr(2));
    set(handles.thumbnail_slider, 'Value', projectStruct.inFile.frameRangeArr(1));

    thumbnail_slider_Callback(handles.thumbnail_slider, '', handles);

    % clamp the in and out points to the current range (in case it changed)
    if(handles.project.frame_in < projectStruct.inFile.frameRangeArr(1))
        handles.project.frame_in = projectStruct.inFile.frameRangeArr(1);
        if(handles.project.frame_out < projectStruct.inFile.frameRangeArr(1))
            handles.project.frame_out = projectStruct.inFile.frameRangeArr(1);
        end
    end
    if(handles.project.frame_out > projectStruct.inFile.frameRangeArr(2))
        handles.project.frame_out = projectStruct.inFile.frameRangeArr(2);
        if(handles.project.frame_in > projectStruct.inFile.frameRangeArr(2))
            handles.project.frame_in = projectStruct.inFile.frameRangeArr(2);
        end
    end

    % show the in and out selections
    set(handles.frame_in_text, 'String', num2str(handles.project.frame_in));
    set(handles.frame_out_text, 'String', num2str(handles.project.frame_out));

    % show the sound bounds selections
    if(isfield(handles.project, 'sound_bounds_arr'))
        set(handles.soundtrack_bounds_table, 'Data', ...
            handles.project.sound_bounds_arr);
    else
        handles.project.sound_bounds_arr = ...
            get(handles.soundtrack_bounds_table, 'Data');
    end

    handles.unsaved_changes = false;

    guidata(hObject,handles);

catch exception
    gui_exception(exception);
end



function [filename, pathname] = save_project_as(project)
try
    [filename, pathname] = uiputfile('*.aeo', 'Save Project');

    if isequal(filename,0) || isequal(pathname,0)
        return;
    end

    p = save_project(project, [pathname filename]);

    if(isempty(p))
        filename = 0;
        pathname = 0;
        return;
    end
catch exception
    gui_exception(exception);
end


function ret = save_project(project, filename)
ret = [];
try
    assert(isfield(project,'projectStruct'), 'must include projectStruct');
    debug_project = project
    debug_filename = filename
    save(filename, 'project');
    ret = project;
catch exception
    ret = [];
    gui_exception(exception);
end


% --- Outputs from this function are returned to the command line.
function varargout = gui_main_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure

if isempty(handles)
varargout{1} = {''};
else
varargout{1} = handles.output;
end

% --------------------------------------------------------------------
function menu_file_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_project_Callback(hObject, eventdata, handles)
% hObject    handle to menu_project (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_help_Callback(hObject, eventdata, handles)
% hObject    handle to menu_help (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_project_source_Callback(hObject, eventdata, handles)
% hObject    handle to menu_project_source (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    new_film_source(hObject);
catch exception
    gui_exception(exception);
end


% --------------------------------------------------------------------
function menu_project_directories_Callback(hObject, eventdata, handles)
% hObject    handle to menu_project_directories (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    gui_directories('gui_main', handles.main_figure);
catch exception
    gui_exception(exception);
end


% --------------------------------------------------------------------
function menu_project_settings_Callback(hObject, eventdata, handles)
% hObject    handle to menu_project_settings (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    gui_project_settings('gui_main', handles.main_figure);
catch exception
    gui_exception(exception);
end


% --------------------------------------------------------------------
function menu_project_render_Callback(hObject, eventdata, handles)
% hObject    handle to menu_project_render (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    gui_extract_sound(handles);
catch exception
    gui_exception(exception);
end


% --------------------------------------------------------------------
function menu_project_delete_Callback(hObject, eventdata, handles)
% hObject    handle to menu_project_delete (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_file_new_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_new (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    new_project(hObject);
catch exception
    gui_exception(exception);
end

% --------------------------------------------------------------------
function menu_file_open_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_open (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    open_project(hObject);
catch exception
    gui_exception(exception);
end

% --------------------------------------------------------------------
function menu_file_save_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_save (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    project = handles.project;
    project.projectStruct = handles.projectStruct;
    if(isfield(handles,'project_file') && ~isempty(handles.project_file))
        save_project(handles.project, handles.project_file);
        handles.unsaved_changes = false;
        guidata(hObject, handles);
    else
        [filename, pathname] = save_project_as(handles.project);
        if(filename == 0)
            return;
        end
        handles.project_file = [pathname filename];
        handles.unsaved_changes = false;
        guidata(hObject, handles);
    end
catch exception
    gui_exception(exception);
end


% --------------------------------------------------------------------
function menu_file_save_as_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_save_as (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    project = handles.project;
    project.projectStruct = handles.projectStruct;
    [filename, pathname] = save_project_as(project);
    if(filename == 0)
        return;
    end
    handles.project_file = [pathname filename];
    handles.unsaved_changes = false;
    guidata(hObject, handles);
catch exception
    gui_exception(exception);
end

% --------------------------------------------------------------------
function menu_file_export_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_export (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    gui_export('gui_main', handles.main_figure);
catch exception
    gui_exception(exception);
end


% --------------------------------------------------------------------
function menu_file_preferences_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_preferences (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    if gui_preferences('gui_main', handles.main_figure)
        handles = guidata(hObject);
        pref = handles.pref;
        save(handles.userfile, 'pref');
    end
catch exception
    gui_exception(exception);
end

% --------------------------------------------------------------------
function menu_file_quit_Callback(hObject, eventdata, handles)
% hObject    handle to menu_file_quit (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    if(close_project(handles))
       close(handles.main_figure);
    end
catch exception
    gui_exception(exception);
end

% --------------------------------------------------------------------
function menu_project_delete_scratch_Callback(hObject, eventdata, handles)
% hObject    handle to menu_project_delete_scratch (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function menu_project_delete_render_Callback(hObject, eventdata, handles)
% hObject    handle to menu_project_delete_render (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    n = size(project.audio_file_arr,2);
    for i=1:n
        delete(project.audio_file_arr{1});
    end
    project.audio_file_arr = [];
catch exception
    gui_exception(exception);
end

% --------------------------------------------------------------------
function menu_help_about_Callback(hObject, eventdata, handles)
% hObject    handle to menu_help_about (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
msgHandle = msgbox({'AEO-Light', '', ...
    ['Version ', handles.versionStr], '',...
    'AEO-Light is an open-source software that extracts audio ' ...
    'from optical sound tracks of motion picture film. AEO-Light is ' ...
    'produced at the University of South Carolina by a team comprised '...
    'of faculty and staff from the University Libraries'' Moving '...
    'Image Research Collections (MIRC) and the College of Arts and '...
    'Science''s Interdisciplinary Mathematics Institute (IMI).'...
    'Project funding comes from the Preservation and Access Division'...
    'of the National Endowment for the Humanities. AEO-Light is '...
    'available through an open-source licensing agreement. The '...
    'complete terms are available in the AEO-Light "ReadMe" file.'}, ...
    'About');

fontSize = 14;
fontName = 'Helvetica';

% get handles to the UIControls ([OK] PushButton) and Text
kids0 = findobj( msgHandle, 'Type', 'UIControl' );
kids1 = findobj( msgHandle, 'Type', 'Text' );

% change the font and fontsize
extent0 = get( kids1, 'Extent' ); % text extent in old font
set( [kids0, kids1], 'FontName', fontName, 'FontSize', fontSize );
extent1 = get( kids1, 'Extent' ); % text extent in new font

% need to resize the msgbox object to accommodate new FontName 
% and FontSize
delta = extent1 - extent0; % change in extent
pos = get( msgHandle, 'Position' ); % msgbox current position
pos = pos + delta; % change size of msgbox
set( msgHandle, 'Position', pos ); % set new position

% --------------------------------------------------------------------
function menu_help_documentation_Callback(hObject, eventdata, handles)
% hObject    handle to menu_help_documentation (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --- Executes during object creation, after setting all properties.
function main_figure_CreateFcn(hObject, eventdata, handles)
% hObject    handle to main_figure (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called


% --- Executes on slider movement.
function thumbnail_slider_Callback(hObject, eventdata, handles)
% hObject    handle to thumbnail_slider (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider
try
    idx = uint32(get(hObject, 'value'));
    % frame = handles.frames.index_array(idx);

    % Read in the specified image.
    doConvertToGray = false;

    %[imageArr, bitDepth] = readImageByIndex(handles.frames.index_array(idx), ...
    %    [handles.frames.directory handles.frames.file_prefix], ...
    %    handles.frames.index_field_length, handles.frames.file_ext, ...
    %    doConvertToGray);

    imageArr = handles.projectStruct.readFramesSafelyFunctHandle(idx, ...
        doConvertToGray);
    bitDepth = handles.projectStruct.workFile.bitDepth;

    % Scale pixel values in case they are integers.
    if (isinteger(imageArr) == true)
        % Compute the number of bits used to store each pixel value.
        storageBitDepth = round(log2(double(intmax(class(imageArr)))));

        % Check if the type used to store the pixel values can accomodate them.
        assert((storageBitDepth >= bitDepth), ...
             'SoundRestoration:soundtrack:TooSmallStorageType', ...
            'Type used to store the pixel values is too small to accomodate them');

        % Scale pixel values to the full range offered by the type used to 
        % store them.
        scale = 2^(storageBitDepth - bitDepth);
        imageArr = imageArr*scale;
    end

    imshow(imageArr);
catch exception
    gui_exception(exception);
end
% end of the function "thumbnail_slider_Callback"


% --- Executes during object creation, after setting all properties.
function thumbnail_slider_CreateFcn(hObject, eventdata, handles)
% hObject    handle to thumbnail_slider (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


% --------------------------------------------------------------------
function toolbar_new_project_ClickedCallback(hObject, eventdata, handles)
% hObject    handle to toolbar_new_project (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    new_project(hObject);
catch exception
    gui_exception(exception);
end

% --------------------------------------------------------------------
function toolbar_open_project_ClickedCallback(hObject, eventdata, handles)
% hObject    handle to toolbar_open_project (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    open_project(hObject);
catch exception
    gui_exception(exception);
end

% --------------------------------------------------------------------
function toolbar_save_project_ClickedCallback(hObject, eventdata, handles)
% hObject    handle to toolbar_save_project (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    project = handles.project;
    project.projectStruct = handles.projectStruct;
    if(isfield(handles,'project_file') && isempty(handles.project_file) == 0)
        save_project(project, handles.project_file);
        handles.unsaved_changes = false;
        guidata(hObject, handles);
    else
        [filename, pathname] = save_project_as(project);
        if(filename == 0)
            return;
        end
        handles.project_file = [pathname filename];
        handles.unsaved_changes = false;
        guidata(hObject, handles);
    end
catch exception
    gui_exception(exception);
end

% --- Executes on button press in logo.
function logo_Callback(hObject, eventdata, handles)
% hObject    handle to logo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --- Executes during object creation, after setting all properties.
function soundtrack_bounds_table_CreateFcn(hObject, eventdata, handles)
% hObject    handle to soundtrack_bounds_table (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called
try
    initTable = [ 0,0,0 ];
    set(hObject, 'Data', initTable);
catch exception
    gui_exception(exception);
end


% --- Executes when selected cell(s) is changed in soundtrack_bounds_table.
function soundtrack_bounds_table_CellSelectionCallback(hObject, eventdata, handles)
% hObject    handle to soundtrack_bounds_table (see GCBO)
% eventdata  structure with the following fields (see UITABLE)
%	Indices: row and column indices of the cell(s) currently selecteds
% handles    structure with handles and user data (see GUIDATA)


% --- Executes when entered data in editable cell(s) in soundtrack_bounds_table.
function soundtrack_bounds_table_CellEditCallback(hObject, eventdata, handles)
% hObject    handle to soundtrack_bounds_table (see GCBO)
% eventdata  structure with the following fields (see UITABLE)
%	Indices: row and column indices of the cell(s) edited
%	PreviousData: previous data for the cell(s) edited
%	EditData: string(s) entered by the user
%	NewData: EditData or its converted form set on the Data property. Empty if Data was not changed
%	Error: error string when failed to convert EditData to appropriate value for Data
% handles    structure with handles and user data (see GUIDATA)
try
    if(size(eventdata.Indices,1) == 0)
        return;
    end

    row = eventdata.Indices(1);
    col = eventdata.Indices(2);
    dataTable = get(hObject,'Data');
    nRows = size(dataTable,1);

    if(col < 3)
        if(row == nRows)
            dataTable(nRows+1,:) = [ 0 0 0 ]
        end
        set(hObject,'Data',dataTable);
        handles.project.sound_bounds_arr = dataTable;
        handles.unsaved_changes = true;
        guidata(hObject, handles);
        return;
    end

    % prevent double-click stacking
    set(hObject, 'Enable', 'off');

    row = eventdata.Indices(1);
    dataTable = get(hObject,'Data');
    nRows = size(dataTable,1);

    if(row == nRows)
        action = 'Edit';
        dataTable(nRows+1,:) = [ 0 0 0 ]; % Add a new last row
    elseif(nRows < 3)
        action = questdlg(['Area #' int2str(row) ' [' int2str(dataTable(row,1)) ...
            '-' int2str(dataTable(row,2)) ']'], ...
         'Action', ...
         'Edit','Cancel','Edit');
    else
        action = questdlg(['Area #' int2str(row) ' [' int2str(dataTable(row,1)) ...
            '-' int2str(dataTable(row,2)) ']'], ...
         'Action', ...
         'Edit','Delete','Cancel','Edit');
    end
    % Handle response
    switch action
        case 'Edit'
            dataTable = gui_sound_bounds(dataTable, row, handles);
        case 'Delete'
            dataTable(row,:) = [];
    end
    if(~strcmp(action,'Cancel'))
        set(hObject,'Data',dataTable);
        handles.project.sound_bounds_arr = dataTable;
        handles.unsaved_changes = true;
        guidata(hObject, handles);
    end
    set(hObject, 'Enable', 'on');
catch exception
    gui_exception(exception);
end


% --------------------------------------------------------------------
function toolbar_extract_sound_ClickedCallback(hObject, eventdata, handles)
% hObject    handle to toolbar_extract_sound (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    gui_extract_sound(handles);
catch exception
    gui_exception(exception);
end


% --- Executes on button press in frame_in_button.
function frame_in_button_Callback(hObject, eventdata, handles)
% hObject    handle to frame_in_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    idx = uint32(get(handles.thumbnail_slider, 'value'));
    %frame = handles.frames.index_array(idx);
    gui_set(handles.frame_in_text, 'String', num2str(idx));
catch exception
    gui_exception(exception);
end


% --- Executes during object creation, after setting all properties.
function frame_in_text_CreateFcn(hObject, eventdata, handles)
% hObject    handle to frame_in_text (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in frame_out_button.
function frame_out_button_Callback(hObject, eventdata, handles)
% hObject    handle to frame_out_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    idx = uint32(get(handles.thumbnail_slider, 'value'));
    %frame = handles.frames.index_array(idx);
    gui_set(handles.frame_out_text, 'String', num2str(idx));
catch exception
    gui_exception(exception);
end



function frame_out_text_Callback(hObject, eventdata, handles)
% hObject    handle to frame_out_text (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of frame_out_text as text
%        str2double(get(hObject,'String')) returns contents of frame_out_text as a double
try
    val = sscanf(get(hObject, 'String'),'%lu');
    cur = val;
    if(isnan(cur))
        cur = handles.projectStruct.inFile.frameRangeArr(1);
    end
    if cur > handles.projectStruct.inFile.frameRangeArr(2)
        cur = handles.projectStruct.inFile.frameRangeArr(2);
    else
        if cur < handles.projectStruct.inFile.frameRangeArr(1)
            cur = handles.projectStruct.inFile.frameRangeArr(1);
        end
        start_val = sscanf(get(handles.frame_in_text, 'String'), '%lu');
        if isnan(start_val)
            start_val = 1;
            handles.project.frame_in = 1;
        end
        if cur < start_val
            set(handles.frame_in_text, 'String', num2str(cur));
            handles.project.frame_in = cur;
        end
    end

    set(hObject, 'String', num2str(cur));
    handles.project.frame_out = cur;
    handles.unsaved_changes = true;
    guidata(hObject, handles);
    set(handles.thumbnail_slider, 'Value', cur);
    thumbnail_slider_Callback(handles.thumbnail_slider, [], handles);
catch exception
    gui_exception(exception);
end

% --- Executes during object creation, after setting all properties.
function frame_out_text_CreateFcn(hObject, eventdata, handles)
% hObject    handle to frame_out_text (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function frame_in_text_Callback(hObject, eventdata, handles)
% hObject    handle to frame_in_text (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of frame_in_text as text
%        str2double(get(hObject,'String')) returns contents of frame_in_text as a double
try
    val = sscanf(get(hObject, 'String'),'%lu');
    cur = val;
    if(isnan(cur))
        cur = handles.projectStruct.inFile.frameRangeArr(1);
    end
    if cur < handles.projectStruct.inFile.frameRangeArr(1)
        cur = handles.projectStruct.inFile.frameRangeArr(1);
    else
        if cur > handles.projectStruct.inFile.frameRangeArr(2)
            cur = handles.projectStruct.inFile.frameRangeArr(2);
        end
        end_val = sscanf(get(handles.frame_out_text, 'String'), '%lu');
        if isnan(end_val)
            end_val = Inf;
            handles.project.frame_out = Inf;
        end
        if cur > end_val
            set(handles.frame_out_text, 'String', num2str(cur));
            handles.project.frame_out = cur;
        end
    end

    set(hObject, 'String', num2str(cur));
    handles.project.frame_in = cur;
    handles.unsaved_changes = true;
    guidata(hObject, handles);
    set(handles.thumbnail_slider, 'Value', cur);
    thumbnail_slider_Callback(handles.thumbnail_slider, [], handles);
catch exception
    gui_exception(exception);
end


% --------------------------------------------------------------------
function toolbar_export_ClickedCallback(hObject, eventdata, handles)
% hObject    handle to toolbar_export (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    gui_export('gui_main', handles.main_figure);
catch exception
    gui_exception(exception);
end


% --- Executes when user attempts to close main_figure.
function main_figure_CloseRequestFcn(hObject, eventdata, handles)
% hObject    handle to main_figure (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: delete(hObject) closes the figure
try
    if(close_project(handles))
        delete(hObject);
    end
catch exception
    gui_exception(exception);
end

% --- Executes on button press in clear_button.
function clear_button_Callback(hObject, eventdata, handles)
% hObject    handle to clear_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    initTable = [ 0,0,0 ];
    set(handles.soundtrack_bounds_table, 'Data', initTable);
    handles.unsaved_changes = true;
    guidata(hObject, handles);
catch exception
    gui_exception(exception);
end


% --------------------------------------------------------------------
function menu_project_show_work_Callback(hObject, eventdata, handles)
% hObject    handle to menu_project_show_work (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    if(ispc)
        [status output] = system(['start ' handles.projectStruct.outFile.outputDir]);
    else
        [status output] = system(['open ' handles.projectStruct.outFile.outputDir]);
    end
catch exception
    gui_exception(exception);
end
    
